/**
 * JSON解析工具函数
 * 提供高可靠性的JSON解析方法，用于处理异常情况
 */

/**
 * 健壮的JSON解析函数
 * 尝试多种方法解析JSON字符串，即使格式不完全符合标准
 * 
 * @param jsonStr - 要解析的JSON字符串
 * @param logPrefix - 可选的日志前缀，用于区分不同组件的日志
 * @returns 解析后的对象，解析失败时抛出异常
 */
export const robustJsonParse = (jsonStr: string, logPrefix: string = ""): any => {
  const log = (msg: string) => console.log(`${logPrefix}${msg}`);
  const error = (msg: string) => console.error(`${logPrefix}${msg}`);
  
  // 1. 首先尝试直接解析
  try {
    return JSON.parse(jsonStr);
  } catch (e) {
    log("直接解析失败，尝试修复JSON");
  }
  
  // 2. 清理非ASCII字符
  let cleanedJson = jsonStr.replace(/[^\x20-\x7E]/g, '');
  try {
    return JSON.parse(cleanedJson);
  } catch (e) {
    log("清理非ASCII后解析失败");
  }
  
  // 3. 提取有效的JSON结构
  try {
    const firstBrace = jsonStr.indexOf('{');
    const lastBrace = jsonStr.lastIndexOf('}');
    if (firstBrace !== -1 && lastBrace !== -1 && firstBrace < lastBrace) {
      const extractedJson = jsonStr.substring(firstBrace, lastBrace + 1);
      return JSON.parse(extractedJson);
    }
  } catch (e) {
    log("结构提取解析失败");
  }
  
  // 4. 尝试通过解析器包装的恢复 - 修复常见的JSON语法错误
  try {
    // 处理未闭合的引号
    let fixedJson = jsonStr;
    // 统计引号数量，如果是奇数，添加一个结束引号
    const quoteCount = (fixedJson.match(/"/g) || []).length;
    if (quoteCount % 2 !== 0) {
      fixedJson += '"';
    }
    
    // 确保大括号闭合
    const openBraces = (fixedJson.match(/{/g) || []).length;
    const closeBraces = (fixedJson.match(/}/g) || []).length;
    if (openBraces > closeBraces) {
      fixedJson += '}'.repeat(openBraces - closeBraces);
    }
    
    // 尝试修复后的JSON
    return JSON.parse(fixedJson);
  } catch (e) {
    log("修复结构后解析失败");
  }
  
  // 5. 尝试使用eval (危险但有时是最后手段)
  try {
    // 只允许在客户端执行
    if (typeof window !== 'undefined') {
      // 注意：这是不安全的，但可能是最后的解析方法
      // 首先检查是否是有效的JSON结构来减轻风险
      if (jsonStr.trim().startsWith('{') && jsonStr.trim().endsWith('}')) {
        return eval(`(${jsonStr})`);
      }
    }
  } catch (e) {
    log("eval解析也失败了");
  }
  
  // 所有解析方法都失败了
  error("所有JSON解析方法都失败");
  throw new Error("无法解析JSON数据");
};

/**
 * 安全的JSON解析函数
 * 与robustJsonParse不同，此函数在解析失败时返回默认值而不是抛出异常
 * 
 * @param jsonStr - 要解析的JSON字符串
 * @param defaultValue - 解析失败时返回的默认值
 * @returns 解析后的对象或默认值
 */
export const safeJsonParse = <T>(jsonStr: string, defaultValue: T): T => {
  try {
    return robustJsonParse(jsonStr) as T;
  } catch (e) {
    console.error("JSON解析失败，返回默认值:", e);
    return defaultValue;
  }
};

/**
 * 安全的JSON字符串化函数
 * 确保即使对象包含循环引用或其他不可序列化的值，也能返回有效的JSON字符串
 * 
 * @param data - 要序列化的对象
 * @returns JSON字符串
 */
export const safeJsonStringify = (data: any): string => {
  try {
    // 预处理对象，确保所有值都可以序列化
    const seen = new WeakSet();
    const replacer = (key: string, value: any) => {
      // 处理循环引用
      if (typeof value === 'object' && value !== null) {
        if (seen.has(value)) {
          return '[循环引用]';
        }
        seen.add(value);
      }
      
      // 处理不可序列化的特殊值
      if (typeof value === 'function') {
        return '[函数]';
      }
      if (value instanceof Error) {
        return `[错误: ${value.message}]`;
      }
      if (value === undefined) {
        return null; // JSON.stringify默认会删除undefined属性
      }
      
      return value;
    };
    
    return JSON.stringify(data, replacer);
  } catch (e) {
    console.error("JSON序列化失败:", e);
    return JSON.stringify({ error: "数据序列化失败" });
  }
};

/**
 * 测试JSON解析的可靠性
 * 可用于诊断和调试JSON解析问题
 * 
 * @param jsonStr - 要测试的JSON字符串
 * @returns 解析结果和使用的方法
 */
export const testJsonParsing = (jsonStr: string): { success: boolean, method?: string, result?: any, error?: string } => {
  console.log("测试JSON解析 - 原始字符串:", jsonStr.substring(0, 200) + (jsonStr.length > 200 ? "..." : ""));
  
  // 方法1: 标准解析
  try {
    const result = JSON.parse(jsonStr);
    return { success: true, method: "标准解析", result };
  } catch (e1) {
    console.log("标准解析失败:", e1);
  }
  
  // 方法2: 清理非ASCII字符
  try {
    const cleaned = jsonStr.replace(/[^\x20-\x7E]/g, '');
    const result = JSON.parse(cleaned);
    return { success: true, method: "清理非ASCII", result };
  } catch (e2) {
    console.log("清理非ASCII后解析失败:", e2);
  }
  
  // 方法3: 提取JSON结构
  try {
    const firstBrace = jsonStr.indexOf('{');
    const lastBrace = jsonStr.lastIndexOf('}');
    if (firstBrace !== -1 && lastBrace !== -1 && firstBrace < lastBrace) {
      const extracted = jsonStr.substring(firstBrace, lastBrace + 1);
      const result = JSON.parse(extracted);
      return { success: true, method: "提取JSON结构", result };
    }
  } catch (e3) {
    console.log("提取JSON结构后解析失败:", e3);
  }
  
  // 方法4: 修复格式
  try {
    // 处理未闭合的引号和大括号
    let fixed = jsonStr;
    const quoteCount = (fixed.match(/"/g) || []).length;
    if (quoteCount % 2 !== 0) {
      fixed += '"';
    }
    
    const openBraces = (fixed.match(/{/g) || []).length;
    const closeBraces = (fixed.match(/}/g) || []).length;
    if (openBraces > closeBraces) {
      fixed += '}'.repeat(openBraces - closeBraces);
    }
    
    const result = JSON.parse(fixed);
    return { success: true, method: "修复格式", result };
  } catch (e4) {
    console.log("修复格式后解析失败:", e4);
  }
  
  // 方法5: eval (仅在客户端)
  if (typeof window !== 'undefined') {
    try {
      if (jsonStr.trim().startsWith('{') && jsonStr.trim().endsWith('}')) {
        const result = eval(`(${jsonStr})`);
        return { success: true, method: "eval", result };
      }
    } catch (e5) {
      console.log("eval解析失败:", e5);
    }
  }
  
  // 所有方法都失败
  return { 
    success: false, 
    error: "所有解析方法都失败",
  };
}; 